建好題目和問答訊息的資料關係後,可以動手做問答聊天室了。
「姐,我先架了之前說的官網範例。你試試看 android 能不能接起來。」我提高音量,因為外面正傳來「少女的祈禱」。
老姐埋首於電腦前,鍵盤「達達」作響。「好,我把 toolbar 上的 navigation icon 和一些 navigation graph 處理完後就來接。」老姐這幾天正在做 App 側邊選單的功能。
我 Ktor 這邊還算順利,直接仿造範例程式碼 https://github.com/ktorio/ktor-samples/tree/63f5a9b9ab8c0576a1957565d1b09675a1292a0e/generic/samples/chat/src/backendMain/kotlin 是可以執行的。
build.gradle
加上對應 Library。
implementation "io.ktor:ktor-websockets:$ktor_version"
ChatServer.kt
直接複製下來。 ChatApplication.kt
則是對應修改。
這行加在 Application.module
外:
private val server = ChatServer()
要安裝 Feature 。
install(WebSockets) {
pingPeriod = Duration.ofMinutes(1)
}
在 routing block
裡加上主要邏輯, Session 改寫成客製化過的 LoginSession :
webSocket("/ws") {
val session= call.sessions.get<LoginSession>()
// We check that we actually have a session. We should always have one,
// since we have defined an interceptor before to set one.
if (session == null) {
close(CloseReason(CloseReason.Codes.VIOLATED_POLICY, "No session"))
return@webSocket
}
// We notify that a member joined by calling the server handler [memberJoin]
// This allows to associate the session id to a specific WebSocket connection.
server.memberJoin(session.id.toString(), this)
try {
// We starts receiving messages (frames).
// Since this is a coroutine. This coroutine is suspended until receiving frames.
// Once the connection is closed, this consumeEach will finish and the code will continue.
incoming.consumeEach { frame ->
// Frames can be [Text], [Binary], [Ping], [Pong], [Close].
// We are only interested in textual messages, so we filter it.
if (frame is Frame.Text) {
// Now it is time to process the text sent from the user.
// At this point we have context about this connection, the session, the text and the server.
// So we have everything we need.
transaction {
User.findById(session.id)?.let {
Chat.new {
master = it
message = frame.readText()
topic = Topic.all().elementAt((0 until Topic.count()).random().toInt())
createdAt = DateTime.now()
}
}
}
server.message(session.id.toString(), frame.readText())
}
}
} finally {
// Either if there was an error, of it the connection was closed gracefully.
// We notify the server that the member left.
server.memberLeft(session.id.toString(), this)
}
}
測試過不影響原本寫的那幾個 http restful api 之後,隨便找了一個線上 websocket 測試網頁輸入路徑 ws://0.0.0.0:8080/ws
,確認我的 server 是能連接的。
也確認資料庫有存下送來的訊息。
一小時後,老姐開始接聊天室,她參考了 https://ktor.io/docs/clients-websockets.html 的範例,可惜遇到了錯誤:
從老姐痛苦的神情可以判斷,今天解決不了這個問題。
沒關係,老姐!我們還有明天,明天繼續努力!
本次鐵人賽的作品在放進更多內容後已經成書,書名是《老姐要用Kotlin寫專案:從 Server 到 Android APP 的開發生存日記》,歡迎購買唷。https://www.tenlong.com.tw/products/9789864348978
不好意思,能請問您ktor參考的官網範例是參考哪篇嗎
還有有完整的github方便讓人參考嗎QAQ
ktor 官網範例程式碼網址就是文章裡面提到的這個,裡面有兩個檔案。 https://github.com/ktorio/ktor-samples/tree/63f5a9b9ab8c0576a1957565d1b09675a1292a0e/generic/samples/chat/src/backendMain/kotlin